﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ACServerSelfHost
{
    abstract class WebAppHostBase
    {
        public WebAppHostBase(Uri baseAddress)
        {
            this.BaseAddress = baseAddress;
            this.state = HostStates.Stop;
            this.CommandList = new ConsoleCommandList();
        }

        private string name;

        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        public Uri BaseAddress
        {
            get; private set;
        }

        private HostStates state;

        public HostStates State
        {
            get { return state; }
            set
            {
                state = value;
                RaiseHostStatusChanged(state);
            }
        }

        public ConsoleCommandList CommandList { get; private set; }

        protected void AddCommandHelp()
        {
            CommandList.Add(new SimpleCommand("This help page", new string[] { "help", "/?" }, (x) => { RaiseLogNotification(CommandList.ToString()); }));
        }

        protected EventHandler<HostStatusChangedEventArgs> HostStatusChangedEvent;
        public event EventHandler<HostStatusChangedEventArgs> HostStatusChanged
        {
            add
            {
                if (HostStatusChangedEvent != null)
                {
                    lock (HostStatusChangedEvent)
                    {
                        HostStatusChangedEvent += value;
                    }
                }
                else
                {
                    HostStatusChangedEvent = new EventHandler<HostStatusChangedEventArgs>(value);
                }
            }
            remove
            {
                if (HostStatusChangedEvent != null)
                {
                    lock (HostStatusChangedEvent)
                    {
                        HostStatusChangedEvent -= value;
                    }
                }
            }
        }

        protected virtual void RaiseHostStatusChanged(HostStates status = HostStates.Stop)
        {
            var args = new HostStatusChangedEventArgs() { CurrentStatus = status };
            EventHandler<HostStatusChangedEventArgs> handler = HostStatusChangedEvent;
            if (handler != null)
            {
                handler(this, args);
            }
        }

        protected EventHandler<LogNotificationEventArgs> LogNotificationEvent;
        public event EventHandler<LogNotificationEventArgs> LogNotification
        {
            add
            {
                if (LogNotificationEvent != null)
                {
                    lock (LogNotificationEvent)
                    {
                        LogNotificationEvent += value;
                    }
                }
                else
                {
                    LogNotificationEvent = new EventHandler<LogNotificationEventArgs>(value);
                }
            }
            remove
            {
                if (LogNotificationEvent != null)
                {
                    lock (LogNotificationEvent)
                    {
                        LogNotificationEvent -= value;
                    }
                }
            }
        }

        protected virtual void RaiseLogNotification(string message, Log.Target target = Log.Target.Output)
        {
            var args = new LogNotificationEventArgs() { Message = message, LogTarget = target };
            EventHandler<LogNotificationEventArgs> handler = LogNotificationEvent;
            if (handler != null)
            {
                handler(this, args);
            }
        }

        public void ExecuteCommand(string commandInput)
        {
            ConsoleCommand command = CommandList.FindByName(commandInput);
            if (command != null)
            {
                command.Execute(commandInput);
            }
            else
            {
                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "Unknown command: \"{0}\"", commandInput), "commandInput");
            }
        }
    }

    [Flags]
    public enum HostStates
    {
        None = 0,
        Stop = 1,
        Run = 2,
        Restart = 3,
    }

    public class HostStatusChangedEventArgs : EventArgs
    {
        public HostStates CurrentStatus { get; set; }
    }
    public class LogNotificationEventArgs : EventArgs
    {
        public string Message { get; set; }
        public Log.Target LogTarget { get; set; }
    }
}
